#include "GameData.h"
#include "GameConfig.h"
#include "../Framework/FormulaDataSupport.h"
GameData* GameData::m_instance = nullptr;

GameData* GameData::getInstance()
{
	if (m_instance == nullptr)
	{
		m_instance = new GameData();
	}
	return m_instance;
}

GameData::GameData()
{
	
}

GameData::~GameData()
{
	m_xmlDoc.reset();
}

void GameData::readConfig()
{
	m_xmlDoc.reset();

	std::string path = FileUtils::getInstance()->fullPathForFilename("Config.xml");
	long size = 0;
	unsigned char* pData = 0;
	pData = FileUtils::getInstance()->getFileData(path.c_str(), "rb", &size);
	pugi::xml_parse_result result = m_xmlDoc.load_buffer(pData, size);
	CC_SAFE_DELETE_ARRAY(pData);

	for (pugi::xml_node node = m_xmlDoc.child("DataGame").child("Mode"); node; node = node.next_sibling("Mode"))
	{
		std::string id = node.attribute("id").as_string();

		if (id == "Easy")
		{
			config.NumOfEasyLevel = atoi(node.child_value("NumMaxLevel"));
			config.MaxLevelFreeEasy = atoi(node.child_value("MaxLevelFree"));
		}
		else if (id == "Normal")
		{
			config.NumOfNormalLevel = atoi(node.child_value("NumMaxLevel"));
			config.MaxLevelFreeNormal = atoi(node.child_value("MaxLevelFree"));
		}
		else if (id == "Hard")
		{
			config.NumOfHardLevel = atoi(node.child_value("NumMaxLevel"));
			config.MaxLevelFreeHard = atoi(node.child_value("MaxLevelFree"));
		}
	}
}

void GameData::readEasy()
{
	m_xmlDoc.reset();

	std::string path = FileUtils::getInstance()->fullPathForFilename("Easy.xml");
	long size = 0;
	unsigned char* pData = 0;
	pData = FileUtils::getInstance()->getFileData(path.c_str(), "rb", &size);
	pugi::xml_parse_result result = m_xmlDoc.load_buffer(pData, size);
	CC_SAFE_DELETE_ARRAY(pData);

	int i = 1;
	for (pugi::xml_node node = m_xmlDoc.child("DataGame").child("Easy"); node; node = node.next_sibling("Easy"))
	{
		LevelData level;
		level.ID = node.attribute("IDLevel").as_int();
		level.Time = atof(node.child_value("Time"));

		std::string type = node.child_value("Type");
		if (type == "Adjust")
			level.Type = EPlayType::kType_Adjust;
		else
			level.Type = EPlayType::kType_Select;

		std::string formula = node.child_value("Formula");
		int bMax = atoi(node.child_value("Bmax"));
		int answerMin = atoi(node.child_value("qMin"));
		int answerMax = atoi(node.child_value("qMax"));
		int formulaCount = atoi(node.child_value("Formulacount"));

		for (int j = 0; j < formulaCount; j++)
		{
			level.listExpression.push_back(FormulaDataSupport::getFormulaData(EGameMode::kMode_Easy, level.ID, level.Type, formula, bMax, answerMin, answerMax));
		}

		dataMode[i] = level;
		i++;
	}
}

void GameData::readNormal()
{
	m_xmlDoc.reset();

	std::string path = FileUtils::getInstance()->fullPathForFilename("Normal.xml");
	long size = 0;
	unsigned char* pData = 0;
	pData = FileUtils::getInstance()->getFileData(path.c_str(), "rb", &size);
	pugi::xml_parse_result result = m_xmlDoc.load_buffer(pData, size);
	CC_SAFE_DELETE_ARRAY(pData);

	int i = 1;
	for (pugi::xml_node node = m_xmlDoc.child("DataGame").child("Normal"); node; node = node.next_sibling("Normal"))
	{
		LevelData level;
		level.ID = node.attribute("IDLevel").as_int();
		level.Time = atof(node.child_value("Time"));

		std::string type = node.child_value("Type");
		if (type == "Adjust")
			level.Type = EPlayType::kType_Adjust;
		else
			level.Type = EPlayType::kType_Select;

		std::string formula = node.child_value("Formula");
		int bMax = atoi(node.child_value("Bmax"));
		int answerMin = atoi(node.child_value("qMin"));
		int answerMax = atoi(node.child_value("qMax"));
		int formulaCount = atoi(node.child_value("Formulacount"));

		for (int j = 0; j < formulaCount; j++)
		{
			level.listExpression.push_back(FormulaDataSupport::getFormulaData(EGameMode::kMode_Normal, level.ID, level.Type, formula, bMax, answerMin, answerMax));
		}

		dataMode[i] = level;
		i++;
	}
}

void GameData::readHard()
{
	m_xmlDoc.reset();

	std::string path = FileUtils::getInstance()->fullPathForFilename("Hard.xml");
	long size = 0;
	unsigned char* pData = 0;
	pData = FileUtils::getInstance()->getFileData(path.c_str(), "rb", &size);
	pugi::xml_parse_result result = m_xmlDoc.load_buffer(pData, size);
	CC_SAFE_DELETE_ARRAY(pData);

	int i = 1;
	for (pugi::xml_node node = m_xmlDoc.child("DataGame").child("Hard"); node; node = node.next_sibling("Hard"))
	{
		LevelData level;
		level.ID = node.attribute("IDLevel").as_int();
		level.Time = atof(node.child_value("Time"));

		std::string type = node.child_value("Type");
		if (type == "Adjust")
			level.Type = EPlayType::kType_Adjust;
		else
			level.Type = EPlayType::kType_Select;

		std::string formula = node.child_value("Formula");
		int bMax = atoi(node.child_value("Bmax"));
		int answerMin = atoi(node.child_value("qMin"));
		int answerMax = atoi(node.child_value("qMax"));
		int formulaCount = atoi(node.child_value("Formulacount"));
		int numGhostStart = atoi(node.child_value("NumGhostStart"));

		for (int j = 0; j < formulaCount; j++)
		{
			Expression expression = FormulaDataSupport::getFormulaData(EGameMode::kMode_Hard, level.ID, level.Type, formula, bMax, answerMin, answerMax);
			if (numGhostStart > 13)
				expression.NumGhostStart = 13;
			else
				expression.NumGhostStart = numGhostStart;

			level.listExpression.push_back(expression);
		}

		dataMode[i] = level;
		i++;
	}
}

int GameData::getMaxNumEquationInLevel(EGameMode gameMode, int currLevel)
{
	switch (gameMode) {
	case kMode_Easy: return (int)dataMode.at(currLevel).listExpression.size();
	case kMode_Normal: return (int)dataMode.at(currLevel).listExpression.size();
	case kMode_Hard: return (int)dataMode.at(currLevel).listExpression.size();
	default:
		break;
	}
}
